package com.UnionPayCenter.wechat;

import com.UnionPayCenter.constant.ComponentConstants;
import com.UnionPayCenter.enums.ErrorCodeEnum;
import com.UnionPayCenter.exception.ApiException;
import com.UnionPayCenter.redis.IRedisService;
import com.UnionPayCenter.util.StringUtils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.TimeUnit;

/**
 * @program: UnionPayServers
 * @description: 微信第三方api接口调用
 * @author: bite
 * @create: 2019-07-21 16:16
 **/
@Slf4j
@Component
public class ComponentUtil {
    @Autowired
    public static IRedisService redisService;

    /**
     * @Description: 第三方--第三方平台接口的调用凭据 令牌（component_access_token
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static String getComponentAccessToken() throws Exception {
        String url = "https://api.weixin.qq.com/cgi-bin/component/api_component_token";

        try {
            String token = redisService.getString(ComponentConstants.ACCESS_TOKEN_REDIS_KEY);
            if (StringUtils.isNullStr(token)) {
                String ticket = redisService.getString(ComponentConstants.TICKET_REDIS_KEY);
                if (!StringUtils.isNullStr(ticket)) {
                    JSONObject params = new JSONObject();
                    params.put("component_appid", ComponentConstants.COMPONENT_APPID);
                    params.put("component_appsecret", ComponentConstants.COMPONENT_APPSECRET);
                    params.put("component_verify_ticket", ticket);

                    String result = WxHttpClient.post(url, params.toString());
                    log.info(String.format("getComponentAccessToken return data: %s", result));
                    if (!StringUtils.isNullStr(result)) {
                        JSONObject json = JSONObject.parseObject(result);
                        if (json.containsKey("component_access_token")) {
                            String accessToken = json.get("component_access_token").toString();
                            redisService.setString(ComponentConstants.ACCESS_TOKEN_REDIS_KEY, accessToken, 7000, TimeUnit.SECONDS);
                            return accessToken;
                        }
                    }
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口的调用凭据失败"));
            }
            return token;
        } catch (Exception e) {
            log.error("第三方平台接口的调用凭据失败", e);
            throw e;
        }
    }

    /**
     * @Description: 第三方--获取预授权码pre_auth_code
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static String getPreAuthCode() throws Exception {
        try {
            String token = getComponentAccessToken();
            String url = "https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?component_access_token=" + token;

            JSONObject params = new JSONObject();
            params.put("component_appid", ComponentConstants.COMPONENT_APPID);

            String result = WxHttpClient.post(url, params.toString());
            log.info(String.format("getPreAuthCode return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.containsKey("pre_auth_code")) {
                    String preAuthCode = json.get("pre_auth_code").toString();
                    return preAuthCode;
                }
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口获取预授权码失败"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口获取预授权码失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口获取预授权码失败", e);
            throw e;
        }
    }


    /**
     * @Description: 第三方--使用授权码获取授权信息
     * @Param: authCode:授权码
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static JSONObject getQueryAuth(String authCode) throws Exception {
        try {
            String token = getComponentAccessToken();
            String url = "https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token=" + token;

            JSONObject params = new JSONObject();
            params.put("component_appid", ComponentConstants.COMPONENT_APPID);
            params.put("authorization_code", authCode);

            String result = WxHttpClient.post(url, params.toString());
            log.info(String.format("getQueryAuth return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.containsKey("authorization_info")) {
                    JSONObject authInfo = json.getJSONObject("authorization_info");
                    if (authInfo != null) {
                        String authAppid = authInfo.getString("authorizer_appid");
                        if (authInfo.containsKey("authorizer_access_token")) {
                            String authorizerAccessToken = authInfo.getString("authorizer_access_token");
                            Integer expiresIn = authInfo.getInteger("expires_in");
                            String authorizerRefreshToken = authInfo.getString("authorizer_refresh_token");

                            redisService.setString(String.format(ComponentConstants.AUTH_ACCESS_TOKEN_REDIS_KEY, authAppid),
                                    authorizerAccessToken, expiresIn - 200, TimeUnit.SECONDS);
                            redisService.setString(String.format(ComponentConstants.AUTH_REFRESH_TOKEN_REDIS_KEY, authAppid),
                                    authorizerRefreshToken);
                        }
                        JSONArray funcInfo = authInfo.getJSONArray("func_info");
                        redisService.setString(String.format(ComponentConstants.AUTH_FUNC_REDIS_KEY, authAppid), funcInfo.toJSONString());
                        return authInfo;
                    }
                }
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口使用授权码获取授权信息失败"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口使用授权码获取授权信息失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口使用授权码获取授权信息失败", e);
            throw e;
        }
    }

    /**
     * @Description: 第三方--获取/刷新接口调用令牌 authorizer_access_token
     * @Param: authAppid:授权方appid
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static String getAuthAccessToken(String authAppid) throws Exception {
        try {
            String authToken = redisService.getString(String.format(ComponentConstants.AUTH_ACCESS_TOKEN_REDIS_KEY, authAppid));
            if (StringUtils.isNullStr(authToken)) {
                String token = getComponentAccessToken();
                String url = "https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token?component_access_token=" + token;
                String refreshToken = redisService.getString(String.format(ComponentConstants.AUTH_REFRESH_TOKEN_REDIS_KEY, authAppid));
                if (!StringUtils.isNullStr(refreshToken)) {
                    JSONObject params = new JSONObject();
                    params.put("component_appid", ComponentConstants.COMPONENT_APPID);
                    params.put("authorizer_appid", authAppid);
                    params.put("authorizer_refresh_token", refreshToken);

                    String result = WxHttpClient.post(url, params.toString());
                    log.info(String.format("getAuthAccessToken return data: %s", result));
                    if (!StringUtils.isNullStr(result)) {
                        JSONObject json = JSONObject.parseObject(result);
                        if (json.containsKey("authorizer_access_token")) {
                            String authorizerAccessToken = json.getString("authorizer_access_token");
                            Integer expiresIn = json.getInteger("expires_in");
                            String authorizerRefreshToken = json.getString("authorizer_refresh_token");

                            redisService.setString(String.format(ComponentConstants.AUTH_ACCESS_TOKEN_REDIS_KEY, authAppid),
                                    authorizerAccessToken, expiresIn - 200, TimeUnit.SECONDS);
                            redisService.setString(String.format(ComponentConstants.AUTH_REFRESH_TOKEN_REDIS_KEY, authAppid),
                                    authorizerRefreshToken);
                            return authorizerAccessToken;
                        }
                    }
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口获取/刷新接口调用令牌失败, 未获得授权"));
            }
            return authToken;
        } catch (Exception e) {
            log.error("第三方平台接口获取/刷新接口调用令牌失败", e);
            throw e;
        }
    }

    /**
     * @Description: 第三方--获取授权方的帐号基本信息
     * @Param: authAppid:授权方appid
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static JSONObject getAuthInfo(String authAppid) throws Exception {
        try {
            String token = getComponentAccessToken();
            String url = "https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info?component_access_token=" + token;

            JSONObject params = new JSONObject();
            params.put("component_appid", ComponentConstants.COMPONENT_APPID);
            params.put("authorizer_appid", authAppid);

            String result = WxHttpClient.post(url, params.toString());
            log.info(String.format("getAuthInfo return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json != null && json.containsKey("authorization_info")) {
                    //authorization_info 授权信息
                    //authorizer_info 公众号/小程序帐号信息
                    return json;
                }
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口获取授权方的帐号基本信息失败"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口获取授权方的帐号基本信息失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口获取授权方的帐号基本信息失败", e);
            throw e;
        }
    }


    /**
     * @Description: 第三方--拉取所有已授权的帐号信息
     * @Param: offset:偏移位置/起始位置
     * @Param: count:拉取数量，最大为 500
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static JSONObject getAuthList(Integer offset, Integer count) throws Exception {
        try {
            String token = getComponentAccessToken();
            String url = "https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_list?component_access_token=" + token;

            JSONObject params = new JSONObject();
            params.put("component_appid", ComponentConstants.COMPONENT_APPID);
            params.put("offset", offset);
            params.put("count", count);

            String result = WxHttpClient.post(url, params.toString());
            log.info(String.format("getAuthList return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json != null) {
                    //total_count 总量
                    //list 公众号/小程序帐号信息列表
                    return json;
                }
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口分页拉取所有已授权的帐号信息失败"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口分页拉取所有已授权的帐号信息失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口分页拉取所有已授权的帐号信息失败", e);
            throw e;
        }
    }


    /**
     * @Description: 公众号/小程序--创建开放平台帐号并绑定公众号/小程序
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static String openCreate(String appid) throws Exception {
        try {
            String token = getAuthAccessToken(appid);
            String url = "https://api.weixin.qq.com/cgi-bin/open/create?access_token=" + token;

            JSONObject params = new JSONObject();
            params.put("appid", appid);

            String result = WxHttpClient.post(url, params.toString());
            log.info(String.format("openCreate return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.getInteger("errcode") == 0) {
                    return json.getString("open_appid");
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), json.getString("errmsg")));
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口创建开放平台帐号并绑定公众号/小程序失败"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口创建开放平台帐号并绑定公众号/小程序失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口创建开放平台帐号并绑定公众号/小程序失败", e);
            throw e;
        }
    }

    /**
     * @Description: 公众号/小程序--将公众号/小程序绑定到开放平台帐号下
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static boolean openBind(String openAppid, String appid) throws Exception {
        try {
            String token = getAuthAccessToken(appid);
            String url = "https://api.weixin.qq.com/cgi-bin/open/bind?access_token=" + token;

            JSONObject params = new JSONObject();
            params.put("appid", appid);
            params.put("open_appid", openAppid);

            String result = WxHttpClient.post(url, params.toString());
            log.info(String.format("openBind return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.getInteger("errcode") == 0) {
                    return true;
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), json.getString("errmsg")));
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口将公众号/小程序绑定到开放平台帐号下失败"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口将公众号/小程序绑定到开放平台帐号下失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口将公众号/小程序绑定到开放平台帐号下失败", e);
            throw e;
        }
    }

    /**
     * @Description: 公众号/小程序--将公众号/小程序从开放平台帐号下解绑
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static boolean openUnbind(String openAppid, String appid) throws Exception {
        try {
            String token = getAuthAccessToken(appid);
            String url = "https://api.weixin.qq.com/cgi-bin/open/unbind?access_token=" + token;

            JSONObject params = new JSONObject();
            params.put("appid", appid);
            params.put("open_appid", openAppid);

            String result = WxHttpClient.post(url, params.toString());
            log.info(String.format("openUnbind return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.getInteger("errcode") == 0) {
                    return true;
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), json.getString("errmsg")));
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口将公众号/小程序从开放平台帐号下解绑失败"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口将公众号/小程序从开放平台帐号下解绑失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口将公众号/小程序从开放平台帐号下解绑失败", e);
            throw e;
        }
    }


    /**
     * @Description: 公众号/小程序--获取公众号/小程序所绑定的开放平台帐号
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static String openGet(String appid) throws Exception {
        try {
            String token = getAuthAccessToken(appid);
            String url = "https://api.weixin.qq.com/cgi-bin/open/get?access_token=" + token;

            JSONObject params = new JSONObject();
            params.put("appid", appid);

            String result = WxHttpClient.post(url, params.toString());
            log.info(String.format("openGet return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.getInteger("errcode") == 0) {
                    return json.getString("open_appid");
                } else if (json.getInteger("errcode") == 89002) {//未绑定
                    return null;
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), json.getString("errmsg")));
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口获取公众号/小程序所绑定的开放平台帐号失败"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口获取公众号/小程序所绑定的开放平台帐号失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口获取公众号/小程序所绑定的开放平台帐号失败", e);
            throw e;
        }
    }

    /**
     * @Description: 公众号--公众号关联小程序
     * @Param: appid:小程序appid
     * @Param: wechatId:公众号appid
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static boolean wxLink(String appid, String wechatId) throws Exception {
        try {
            String token = getAuthAccessToken(wechatId);
            String url = "https://api.weixin.qq.com/cgi-bin/wxopen/wxamplink?access_token=" + token;

            JSONObject params = new JSONObject();
            params.put("appid", appid);//小程序 appid
            params.put("notify_users", 1);//是否发送模板消息通知公众号粉丝
            params.put("show_profile", 1);//是否展示公众号主页中

            String result = WxHttpClient.post(url, params.toString());
            log.info(String.format("wxLink return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.getInteger("errcode") == 0) {
                    return true;
                } else if (json.getInteger("errcode") == 89015) {//已关联
                    return true;
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), json.getString("errmsg")));
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口公众号关联小程序失败"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口公众号关联小程序失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口公众号关联小程序失败", e);
            throw e;
        }
    }

    /**
     * @Description: 小程序--服务通知-获取帐号下的模板列表
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static JSONArray serviceTemplateList(String appid, Integer offset, Integer count) throws Exception {
        try {
            String token = getAuthAccessToken(appid);
            String url = "https://api.weixin.qq.com/cgi-bin/wxopen/template/list?access_token=" + token;

            JSONObject params = new JSONObject();
            params.put("offset", offset);
            params.put("count", count);

            String result = WxHttpClient.post(url, params.toString());
            log.info(String.format("serviceTemplateList return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.getInteger("errcode") == 0) {
                    return json.getJSONArray("list");
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), json.getString("errmsg")));
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口服务通知-获取帐号下的模板列表"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口服务通知-获取帐号下的模板列表失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口服务通知-获取帐号下的模板列表失败", e);
            throw e;
        }
    }

    /**
     * @Description: 小程序--服务通知-组合模板并添加到个人模板库
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static String serviceTemplate(String appid, String id, JSONArray keywordIdList) throws Exception {
        try {
            String token = getAuthAccessToken(appid);
            String url = "https://api.weixin.qq.com/cgi-bin/wxopen/template/add?access_token=" + token;

            JSONObject params = new JSONObject();
            params.put("id", id);
            params.put("keyword_id_list", keywordIdList);

            String result = WxHttpClient.post(url, params.toString());
            log.info(String.format("serviceTemplate return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.getInteger("errcode") == 0) {
                    return json.getString("template_id");
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), json.getString("errmsg")));
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口服务通知-组合模板并添加到个人模板库"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口服务通知-组合模板并添加到个人模板库失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口服务通知-组合模板并添加到个人模板库失败", e);
            throw e;
        }
    }

    public static String getTemplate(String appid, String id) throws Exception {
        try {
            String token = getAuthAccessToken(appid);
            String url = "https://api.weixin.qq.com/cgi-bin/wxopen/template/library/get?access_token=" + token;

            JSONObject params = new JSONObject();
            params.put("id", id);

            String result = WxHttpClient.post(url, params.toString());
            log.info(String.format("get template return data: %s", result));
            return result;
        } catch (ApiException e) {
            log.error("get template error, code {}, message {}", e.getCode(), e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("get template error: ", e.getMessage(), e);
            throw e;
        }
    }

    /**
     * @Description: 第三方--获取代码草稿列表
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static JSONArray getTemplateDraftList() throws Exception {
        try {
            String token = getComponentAccessToken();
            String url = "https://api.weixin.qq.com/wxa/gettemplatedraftlist?access_token=" + token;

            String result = WxHttpClient.get(url);
            log.info(String.format("getTemplateDraftList return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.getInteger("errcode") == 0) {
                    return json.getJSONArray("draft_list");
                } else if (json.getInteger("errcode") == 85064) {
                    return null;
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), json.getString("errmsg")));
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口获取代码草稿列表失败"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口获取代码草稿列表失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口获取代码草稿列表失败", e);
            throw e;
        }
    }

    /**
     * @Description: 第三方--将草稿添加到代码模板库
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static boolean addToTemplate(String draftId) throws Exception {
        try {
            String token = getComponentAccessToken();
            String url = "https://api.weixin.qq.com/wxa/addtotemplate?access_token=" + token;

            JSONObject params = new JSONObject();
            params.put("draft_id", draftId);

            String result = WxHttpClient.post(url, params.toString());
            log.info(String.format("addToTemplate return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.getInteger("errcode") == 0) {
                    return true;
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), json.getString("errmsg")));
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口将草稿添加到代码模板库"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口将草稿添加到代码模板库失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口将草稿添加到代码模板库失败", e);
            throw e;
        }
    }

    /**
     * @Description: 第三方--获取代码模板列表
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static JSONArray getTemplateList() throws Exception {
        try {
            String token = getComponentAccessToken();
            String url = "https://api.weixin.qq.com/wxa/gettemplatelist?access_token=" + token;

            String result = WxHttpClient.get(url);
            log.info(String.format("getTemplateList return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.getInteger("errcode") == 0) {
                    return json.getJSONArray("template_list");
                } else if (json.getInteger("errcode") == 85064) {
                    return null;
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), json.getString("errmsg")));
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口获取代码模板列表失败"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口获取代码模板列表失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口获取代码模板列表失败", e);
            throw e;
        }
    }

    /**
     * @Description: 第三方--删除指定代码模版
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static boolean deleteTemplate(String templateId) throws Exception {
        try {
            String token = getComponentAccessToken();
            String url = "https://api.weixin.qq.com/wxa/deletetemplate?access_token=" + token;

            JSONObject params = new JSONObject();
            params.put("template_id", templateId);

            String result = WxHttpClient.post(url, params.toString());
            log.info(String.format("deleteTemplate return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.getInteger("errcode") == 0) {
                    return true;
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), json.getString("errmsg")));
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口删除指定代码模版"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口删除指定代码模版失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口删除指定代码模版失败", e);
            throw e;
        }
    }

    /**
     * @Description: 小程序--绑定微信用户为体验者
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static String bindTester(String appid, String wechatid) throws Exception {
        try {
            String token = getAuthAccessToken(appid);
            String url = "https://api.weixin.qq.com/wxa/bind_tester?access_token=" + token;

            JSONObject params = new JSONObject();
            params.put("wechatid", wechatid);

            String result = WxHttpClient.post(url, params.toString());
            log.info(String.format("bindTester return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.getInteger("errcode") == 0) {
                    return json.getString("userstr");
                } else if (json.getInteger("errcode") == 85004) {
                    return null;
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), json.getString("errmsg")));
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口绑定微信用户为体验者"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口绑定微信用户为体验者失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口绑定微信用户为体验者失败", e);
            throw e;
        }
    }

    /**
     * @Description: 小程序--解除绑定体验者
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static boolean unbindTester(String appid, String wechatid) throws Exception {
        try {
            String token = getAuthAccessToken(appid);
            String url = "https://api.weixin.qq.com/wxa/unbind_tester?access_token=" + token;

            JSONObject params = new JSONObject();
            params.put("wechatid", wechatid);

            String result = WxHttpClient.post(url, params.toString());
            log.info(String.format("unbindTester return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.getInteger("errcode") == 0) {
                    return true;
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), json.getString("errmsg")));
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口解除绑定体验者"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口解除绑定体验者失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口解除绑定体验者失败", e);
            throw e;
        }
    }

    /**
     * @Description: 小程序--设置服务器域名
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static boolean modifyDomain(String appid, String action, JSONArray requestdomain, JSONArray wsrequestdomain,
                                       JSONArray uploaddomain, JSONArray downloaddomain) throws Exception {
        try {
            String token = getAuthAccessToken(appid);
            String url = "https://api.weixin.qq.com/wxa/modify_domain?access_token=" + token;

            JSONObject params = new JSONObject();
            params.put("action", action);
            if (!"get".equals(action)) {
                params.put("requestdomain", requestdomain);
                params.put("wsrequestdomain", wsrequestdomain);
                params.put("uploaddomain", uploaddomain);
                params.put("downloaddomain", downloaddomain);
            }

            String result = WxHttpClient.post(url, params.toString());
            log.info(String.format("modifyDomain return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.getInteger("errcode") == 0 || json.getInteger("errcode") == 85017) {
                    return true;
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), json.getString("errmsg")));
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口设置服务器域名"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口设置服务器域名失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口设置服务器域名失败", e);
            throw e;
        }
    }

    /**
     * @Description: 小程序--设置业务域名
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static boolean setWebViewDomain(String appid, String action, JSONArray webviewdomain) throws Exception {
        try {
            String token = getAuthAccessToken(appid);
            String url = "https://api.weixin.qq.com/wxa/setwebviewdomain?access_token=" + token;

            JSONObject params = new JSONObject();
            if (!StringUtils.isNullStr(action)) {
                params.put("action", action);
            }
            params.put("webviewdomain", webviewdomain);

            String result = WxHttpClient.post(url, params.toString());
            log.info(String.format("setWebViewDomain return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.getInteger("errcode") == 0) {
                    return true;
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), json.getString("errmsg")));
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口设置业务域名"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口设置业务域名失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口设置业务域名失败", e);
            throw e;
        }
    }

    /**
     * @Description: 小程序--获取审核时可填写的类目信息
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static JSONArray getCategory(String appid) throws Exception {
        try {
            String token = getAuthAccessToken(appid);
            String url = "https://api.weixin.qq.com/wxa/get_category?access_token=" + token;

            String result = WxHttpClient.get(url);
            log.info(String.format("getCategory return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.getInteger("errcode") == 0) {
                    return json.getJSONArray("category_list");
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), json.getString("errmsg")));
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口获取审核时可填写的类目信息"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口获取审核时可填写的类目信息失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口获取审核时可填写的类目信息失败", e);
            throw e;
        }
    }

    /**
     * @Description: 小程序--上传小程序代码
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static boolean codeCommit(String appid, String templateId, String extJson, String userVersion, String userDesc) throws Exception {
        try {
            String token = getAuthAccessToken(appid);
            String url = "https://api.weixin.qq.com/wxa/commit?access_token=" + token;

            JSONObject params = new JSONObject();
            params.put("template_id", templateId);
            params.put("ext_json", extJson);
            params.put("user_version", userVersion);
            params.put("user_desc", userDesc);

            String result = WxHttpClient.post(url, params.toString());
            log.info(String.format("codeCommit return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.getInteger("errcode") == 0) {
                    return true;
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), json.getString("errmsg")));
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口上传小程序代码"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口上传小程序代码失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口上传小程序代码失败", e);
            throw e;
        }
    }

    /**
     * @Description: 小程序--获取已上传的代码的页面列表
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static JSONArray codeGetPage(String appid) throws Exception {
        try {
            String token = getAuthAccessToken(appid);
            String url = "https://api.weixin.qq.com/wxa/get_page?access_token=" + token;

            String result = WxHttpClient.get(url);
            log.info(String.format("codeGetPage return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.getInteger("errcode") == 0) {
                    return json.getJSONArray("page_list");
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), json.getString("errmsg")));
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口获取已上传的代码的页面列表"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口获取已上传的代码的页面列表失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口获取已上传的代码的页面列表失败", e);
            throw e;
        }
    }

    /**
     * @Description: 获取的体验版二维码
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/10
     */
    public static boolean codeGetQrcode(String appid, String name) throws Exception {

        try {
            String token = getAuthAccessToken(appid);
            String urlStr = "https://api.weixin.qq.com/wxa/get_qrcode?access_token=" + token;
            //建立http连接
            URL url = new URL(urlStr);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setDoOutput(true);
            urlConnection.setDoInput(true);
            urlConnection.setRequestMethod("GET");
            urlConnection.setUseCaches(false);
            urlConnection.setRequestProperty("Content-Type", "application/json");
            urlConnection.connect();

            InputStream inputStream = urlConnection.getInputStream();

            if (inputStream != null) {
                try {
                    String path = ClassUtils.getDefaultClassLoader().getResource("").getPath() + "static" + name;
                    File file = new File(path);
                    FileOutputStream fos = new FileOutputStream(file);
                    byte[] b = new byte[1024];
                    int nRead = 0;
                    while ((nRead = inputStream.read(b)) != -1) {
                        fos.write(b, 0, nRead);
                    }
                    fos.flush();
                    fos.close();

                    log.info(String.format("codeGetQrcode path：%s success", name));
                    return true;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            return false;
        } catch (Exception e) {
            log.error("第三方平台接口获取的体验版二维码失败", e);
            throw e;
        }
    }

    /**
     * @Description: 小程序--提交审核
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static String codeSubmitAudit(String appid, JSONArray itemList) throws Exception {
        try {
            String token = getAuthAccessToken(appid);
            String url = "https://api.weixin.qq.com/wxa/submit_audit?access_token=" + token;

            JSONObject params = new JSONObject();
            params.put("item_list", itemList);

            String result = WxHttpClient.post(url, params.toString());
            log.info(String.format("codeSubmitAudit return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.getInteger("errcode") == 0) {
                    return json.getString("auditid");
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), json.getString("errmsg")));
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口提交审核"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口提交审核失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口提交审核失败", e);
            throw e;
        }
    }

    /**
     * @Description: 小程序--查询指定发布审核单的审核状态
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static JSONObject codeGetAuditstatus(String appid, String auditid) throws Exception {
        try {
            String token = getAuthAccessToken(appid);
            String url = "https://api.weixin.qq.com/wxa/get_auditstatus?access_token=" + token;

            JSONObject params = new JSONObject();
            params.put("auditid", auditid);

            String result = WxHttpClient.post(url, params.toString());
            log.info(String.format("codeGetAuditstatus return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.getInteger("errcode") == 0) {
                    return json;
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), json.getString("errmsg")));
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口查询指定发布审核单的审核状态"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口查询指定发布审核单的审核状态失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口查询指定发布审核单的审核状态失败", e);
            throw e;
        }
    }

    /**
     * @Description: 小程序--查询最新一次提交的审核状态
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static JSONObject codeGetLatestAuditstatus(String appid) throws Exception {
        try {
            String token = getAuthAccessToken(appid);
            String url = "https://api.weixin.qq.com/wxa/get_latest_auditstatus?access_token=" + token;

            String result = WxHttpClient.get(url);
            log.info(String.format("codeGetLatestAuditstatus return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.getInteger("errcode") == 0) {
                    return json;
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), json.getString("errmsg")));
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口查询最新一次提交的审核状态"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口查询最新一次提交的审核状态失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口查询最新一次提交的审核状态失败", e);
            throw e;
        }
    }

    /**
     * @Description: 小程序--小程序审核撤回
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static boolean codeUndocodeaudit(String appid) throws Exception {
        try {
            String token = getAuthAccessToken(appid);
            String url = "https://api.weixin.qq.com/wxa/undocodeaudit?access_token=" + token;

            String result = WxHttpClient.get(url);
            log.info(String.format("codeUndocodeaudit return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.getInteger("errcode") == 0) {
                    return true;
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), json.getString("errmsg")));
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口小程序审核撤回"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口小程序审核撤回失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口小程序审核撤回失败", e);
            throw e;
        }
    }

    /**
     * @Description: 小程序--发布已通过审核的小程序
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static boolean codeRelease(String appid) throws Exception {
        try {
            String token = getAuthAccessToken(appid);
            String url = "https://api.weixin.qq.com/wxa/release?access_token=" + token;

            JSONObject params = new JSONObject();

            String result = WxHttpClient.post(url, params.toString());
            log.info(String.format("codeRelease return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.getInteger("errcode") == 0) {
                    return true;
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), json.getString("errmsg")));
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口发布已通过审核的小程序"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口发布已通过审核的小程序失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口发布已通过审核的小程序失败", e);
            throw e;
        }
    }

    /**
     * @Description: 小程序--版本回退
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static boolean codeRevertcoderelease(String appid) throws Exception {
        try {
            String token = getAuthAccessToken(appid);
            String url = "https://api.weixin.qq.com/wxa/revertcoderelease?access_token=" + token;

            String result = WxHttpClient.get(url);
            log.info(String.format("codeRevertcoderelease return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.getInteger("errcode") == 0) {
                    return true;
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), json.getString("errmsg")));
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口版本回退"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口版本回退失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口版本回退失败", e);
            throw e;
        }
    }

    /**
     * @Description: 公众号--客服消息接口
     * @Param:
     * @return:
     * @Author: bite
     * @Date: 2019/7/21
     */
    public static boolean send(String appid, String touser, String content) throws Exception {
        try {

            String token = getAuthAccessToken(appid);
            String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + token;

            JSONObject con = new JSONObject();
            con.put("content", content);

            JSONObject params = new JSONObject();
            params.put("touser", touser);
            params.put("msgtype", "text");
            params.put("text", con);

            String result = WxHttpClient.post(url, params.toString());
            log.info(String.format("send return data: %s", result));
            if (!StringUtils.isNullStr(result)) {
                JSONObject json = JSONObject.parseObject(result);
                if (json.getInteger("errcode") == 0) {
                    return true;
                }
                throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), json.getString("errmsg")));
            }
            throw new ApiException(ErrorCodeEnum.SW12.code(), String.format(ErrorCodeEnum.SW12.msg(), "第三方平台接口客服消息接口"));
        } catch (ApiException e) {
            log.error(String.format("第三方平台接口客服消息接口失败，错误信息：%s", e.getMessage()));
            throw e;
        } catch (Exception e) {
            log.error("第三方平台接口客服消息接口失败", e);
            throw e;
        }
    }
}
